package cn.iocoder.lw.module.core.service.evaluation;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.lw.framework.common.pojo.PageResult;
import cn.iocoder.lw.framework.common.util.object.BeanUtils;
import cn.iocoder.lw.module.core.controller.admin.evaluation.vo.evaluation.CoreWorkOrderEvaluationPageReqVO;
import cn.iocoder.lw.module.core.controller.admin.evaluation.vo.evaluation.CoreWorkOrderEvaluationSaveReqVO;
import cn.iocoder.lw.module.core.controller.app.evaluation.vo.evaluation.AppCoreWorkOrderEvaluationCreateReqVO;
import cn.iocoder.lw.module.core.controller.app.evaluation.vo.evaluation.AppCoreWorkOrderEvaluationUpdateReqVO;
import cn.iocoder.lw.module.core.dal.dataobject.evaluation.CoreWorkOrderEvaluationDO;
import cn.iocoder.lw.module.core.dal.dataobject.workorder.CoreWorkOrderDO;
import cn.iocoder.lw.module.core.dal.mysql.evaluation.CoreWorkOrderEvaluationMapper;
import cn.iocoder.lw.module.core.enums.evaluation.EvaluationLevelEnum;
import cn.iocoder.lw.module.core.service.workorder.CoreWorkOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static cn.iocoder.lw.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.lw.module.core.enums.ErrorCodeConstants.*;

/**
 * 工单评价 Service 实现类
 *
 * @author Lw源码
 */
@Service
@Validated
@Slf4j
public class CoreWorkOrderEvaluationServiceImpl implements CoreWorkOrderEvaluationService {

    @Resource
    private CoreWorkOrderEvaluationMapper evaluationMapper;

    @Resource
    private CoreWorkOrderService workOrderService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createEvaluation(@Valid CoreWorkOrderEvaluationSaveReqVO createReqVO) {
        // 校验工单存在且已完成
        validateWorkOrderForEvaluation(createReqVO.getWorkOrderId());
        // 校验是否已评价
        validateEvaluationNotExists(createReqVO.getWorkOrderId());

        // 计算评价等级
        Integer evaluationLevel = calculateEvaluationLevel(createReqVO.getOverallScore(),
                createReqVO.getServiceAttitudeScore(),
                createReqVO.getProfessionalSkillScore(),
                createReqVO.getResponseSpeedScore());

        // 插入
        CoreWorkOrderEvaluationDO evaluation = BeanUtils.toBean(createReqVO, CoreWorkOrderEvaluationDO.class);
        evaluation.setEvaluationLevel(evaluationLevel);
        evaluation.setAnonymous(evaluation.getAnonymous() != null ? evaluation.getAnonymous() : false);
        evaluation.setRead(false);
        evaluationMapper.insert(evaluation);

        // 更新工单状态为已评价（可选）
        updateWorkOrderEvaluationStatus(createReqVO.getWorkOrderId());

        return evaluation.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createEvaluationApp(@Valid AppCoreWorkOrderEvaluationCreateReqVO createReqVO) {
        // 校验工单存在且已完成
        validateWorkOrderForEvaluation(createReqVO.getWorkOrderId());
        // 校验是否已评价
        validateEvaluationNotExists(createReqVO.getWorkOrderId());

        // 计算评价等级
        Integer evaluationLevel = calculateEvaluationLevel(createReqVO.getOverallScore(),
                createReqVO.getServiceAttitudeScore(),
                createReqVO.getProfessionalSkillScore(),
                createReqVO.getResponseSpeedScore());

        // 插入
        CoreWorkOrderEvaluationDO evaluation = BeanUtils.toBean(createReqVO, CoreWorkOrderEvaluationDO.class);
        evaluation.setEvaluationLevel(evaluationLevel);
        evaluation.setAnonymous(evaluation.getAnonymous() != null ? evaluation.getAnonymous() : false);
        evaluation.setRead(false);
        evaluationMapper.insert(evaluation);

        // 更新工单状态为已评价（可选）
        updateWorkOrderEvaluationStatus(createReqVO.getWorkOrderId());

        return evaluation.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateEvaluation(@Valid CoreWorkOrderEvaluationSaveReqVO updateReqVO) {
        // 校验存在
        validateEvaluationExists(updateReqVO.getId());
        // 更新
        CoreWorkOrderEvaluationDO updateObj = BeanUtils.toBean(updateReqVO, CoreWorkOrderEvaluationDO.class);
        evaluationMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateEvaluationApp(@Valid AppCoreWorkOrderEvaluationUpdateReqVO updateReqVO) {
        // 校验存在
        validateEvaluationExists(updateReqVO.getId());
        // 更新
        CoreWorkOrderEvaluationDO updateObj = BeanUtils.toBean(updateReqVO, CoreWorkOrderEvaluationDO.class);
        evaluationMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteEvaluation(Long id) {
        // 校验存在
        validateEvaluationExists(id);
        // 删除
        evaluationMapper.deleteById(id);
    }

    @Override
    public CoreWorkOrderEvaluationDO getEvaluation(Long id) {
        return evaluationMapper.selectById(id);
    }

    @Override
    public PageResult<CoreWorkOrderEvaluationDO> getEvaluationPage(CoreWorkOrderEvaluationPageReqVO pageReqVO) {
        return evaluationMapper.selectPage(pageReqVO);
    }

    @Override
    public CoreWorkOrderEvaluationDO validateEvaluationExists(Long id) {
        if (id == null) {
            return null;
        }
        CoreWorkOrderEvaluationDO evaluation = evaluationMapper.selectById(id);
        if (evaluation == null) {
            throw exception(EVALUATION_NOT_EXISTS);
        }
        return evaluation;
    }

    @Override
    public CoreWorkOrderEvaluationDO getEvaluationByWorkOrderId(Long workOrderId) {
        return evaluationMapper.selectByWorkOrderId(workOrderId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void merchantReply(Long id, String reply) {
        CoreWorkOrderEvaluationDO evaluation = validateEvaluationExists(id);

        // 更新回复
        CoreWorkOrderEvaluationDO updateObj = new CoreWorkOrderEvaluationDO();
        updateObj.setId(id);
        updateObj.setMerchantReply(reply);
        updateObj.setMerchantReplyTime(LocalDateTime.now());
        evaluationMapper.updateById(updateObj);

        log.info("商家回复评价，评价编号: {}, 回复内容: {}", id, reply);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void markAsRead(Long id) {
        CoreWorkOrderEvaluationDO evaluation = validateEvaluationExists(id);

        if (!Boolean.TRUE.equals(evaluation.getRead())) {
            CoreWorkOrderEvaluationDO updateObj = new CoreWorkOrderEvaluationDO();
            updateObj.setId(id);
            updateObj.setRead(true);
            evaluationMapper.updateById(updateObj);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchMarkAsRead(List<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return;
        }

        List<CoreWorkOrderEvaluationDO> evaluations = evaluationMapper.selectBatchIds(ids);
        List<Long> unreadIds = evaluations.stream()
                .filter(evaluation -> !Boolean.TRUE.equals(evaluation.getRead()))
                .map(CoreWorkOrderEvaluationDO::getId)
                .collect(Collectors.toList());

        if (CollUtil.isNotEmpty(unreadIds)) {
            unreadIds.forEach(id -> {
                CoreWorkOrderEvaluationDO updateObj = new CoreWorkOrderEvaluationDO();
                updateObj.setId(id);
                updateObj.setRead(true);
                evaluationMapper.updateById(updateObj);
            });
        }
    }

    @Override
    public List<CoreWorkOrderEvaluationDO> getEvaluationListByInitiatorId(Long initiatorId) {
        return evaluationMapper.selectListByInitiatorId(initiatorId);
    }

    @Override
    public List<CoreWorkOrderEvaluationDO> getEvaluationListByAssigneeId(Long assigneeId) {
        return evaluationMapper.selectListByAssigneeId(assigneeId);
    }

    @Override
    public List<CoreWorkOrderEvaluationDO> getUnreadEvaluations() {
        return evaluationMapper.selectUnreadEvaluations();
    }

    @Override
    public List<CoreWorkOrderEvaluationDO> getUnreadEvaluationsByAssigneeId(Long assigneeId) {
        return evaluationMapper.selectUnreadEvaluationsByAssigneeId(assigneeId);
    }

    @Override
    public Map<String, Object> getEvaluationStatistics(Long assigneeId) {
        List<CoreWorkOrderEvaluationDO> evaluations = assigneeId != null ?
                evaluationMapper.selectListByAssigneeId(assigneeId) :
                evaluationMapper.selectList(); // 获取所有评价

        if (CollUtil.isEmpty(evaluations)) {
            return createEmptyStatistics();
        }

        Map<String, Object> statistics = new HashMap<>();

        // 总评价数
        statistics.put("totalCount", evaluations.size());

        // 各等级评价数量
        Map<Integer, Long> levelCountMap = evaluations.stream()
                .collect(Collectors.groupingBy(CoreWorkOrderEvaluationDO::getEvaluationLevel, Collectors.counting()));

        statistics.put("verySatisfiedCount", levelCountMap.getOrDefault(EvaluationLevelEnum.VERY_SATISFIED.getLevel(), 0L));
        statistics.put("satisfiedCount", levelCountMap.getOrDefault(EvaluationLevelEnum.SATISFIED.getLevel(), 0L));
        statistics.put("averageCount", levelCountMap.getOrDefault(EvaluationLevelEnum.AVERAGE.getLevel(), 0L));
        statistics.put("unsatisfiedCount", levelCountMap.getOrDefault(EvaluationLevelEnum.UNSATISFIED.getLevel(), 0L));
        statistics.put("veryUnsatisfiedCount", levelCountMap.getOrDefault(EvaluationLevelEnum.VERY_UNSATISFIED.getLevel(), 0L));

        // 平均分
        Double averageScore = getAverageScore(assigneeId);
        statistics.put("averageScore", averageScore != null ? averageScore : 0.0);

        // 满意率（4分及以上为满意）
        long satisfiedCount = levelCountMap.getOrDefault(EvaluationLevelEnum.VERY_SATISFIED.getLevel(), 0L) +
                              levelCountMap.getOrDefault(EvaluationLevelEnum.SATISFIED.getLevel(), 0L);
        double satisfactionRate = evaluations.size() > 0 ? (double) satisfiedCount / evaluations.size() * 100 : 0;
        statistics.put("satisfactionRate", satisfactionRate);

        return statistics;
    }

    @Override
    public Double getAverageScore(Long assigneeId) {
        List<CoreWorkOrderEvaluationDO> evaluations = assigneeId != null ?
                evaluationMapper.selectListByAssigneeId(assigneeId) :
                evaluationMapper.selectList();

        if (CollUtil.isEmpty(evaluations)) {
            return null;
        }

        return evaluations.stream()
                .mapToInt(evaluation -> evaluation.getOverallScore() != null ? evaluation.getOverallScore() : 0)
                .average()
                .orElse(0.0);
    }

    @Override
    public List<CoreWorkOrderEvaluationDO> getEvaluationList(CoreWorkOrderEvaluationPageReqVO pageReqVO) {
        // 简化实现，设置大页面大小获取所有数据
        pageReqVO.setPageSize(10000);
        PageResult<CoreWorkOrderEvaluationDO> pageResult = evaluationMapper.selectPage(pageReqVO);
        return pageResult.getList();
    }

    /**
     * 校验工单是否可以评价
     */
    private void validateWorkOrderForEvaluation(Long workOrderId) {
        CoreWorkOrderDO workOrder = workOrderService.getWorkOrder(workOrderId);
        if (workOrder == null) {
            throw exception(WORK_ORDER_NOT_EXISTS);
        }
        // TODO: 校验工单状态是否为已完成
        // if (!Objects.equals(workOrder.getStatus(), WorkOrderStatusEnum.COMPLETED.getStatus())) {
        //     throw exception(WORK_ORDER_NOT_COMPLETED);
        // }
    }

    /**
     * 校验工单是否已评价
     */
    private void validateEvaluationNotExists(Long workOrderId) {
        CoreWorkOrderEvaluationDO existingEvaluation = evaluationMapper.selectByWorkOrderId(workOrderId);
        if (existingEvaluation != null) {
            throw exception(EVALUATION_ALREADY_EXISTS);
        }
    }

    /**
     * 计算评价等级
     */
    private Integer calculateEvaluationLevel(Integer overallScore, Integer serviceAttitudeScore,
                                             Integer professionalSkillScore, Integer responseSpeedScore) {
        List<Integer> scores = new ArrayList<>();
        if (overallScore != null) scores.add(overallScore);
        if (serviceAttitudeScore != null) scores.add(serviceAttitudeScore);
        if (professionalSkillScore != null) scores.add(professionalSkillScore);
        if (responseSpeedScore != null) scores.add(responseSpeedScore);

        if (scores.isEmpty()) {
            return EvaluationLevelEnum.AVERAGE.getLevel();
        }

        double averageScore = scores.stream().mapToInt(Integer::intValue).average().orElse(3.0);
        return EvaluationLevelEnum.getByScore(averageScore).getLevel();
    }

    /**
     * 更新工单评价状态
     */
    private void updateWorkOrderEvaluationStatus(Long workOrderId) {
        // TODO: 可以更新工单状态为已评价，或添加评价标识
        log.debug("更新工单评价状态，工单ID: {}", workOrderId);
    }

    /**
     * 创建空的统计信息
     */
    private Map<String, Object> createEmptyStatistics() {
        Map<String, Object> statistics = new HashMap<>();
        statistics.put("totalCount", 0);
        statistics.put("verySatisfiedCount", 0);
        statistics.put("satisfiedCount", 0);
        statistics.put("averageCount", 0);
        statistics.put("unsatisfiedCount", 0);
        statistics.put("veryUnsatisfiedCount", 0);
        statistics.put("averageScore", 0.0);
        statistics.put("satisfactionRate", 0.0);
        return statistics;
    }

}